'abutime.monkey by Belimoth

'TODO
'	move everything appropriate into Time class
'	fixed rate logic
'	UpdateTime:Void( timePassed:Int = -1 )

Strict
Import mojo



Const UNIT_MILLISECONDS:Int = 0
Const UNIT_SECONDS:Int = 1
Const UNIT_FRAMES:Int = 2



Interface IJuggleable
	Method Active:Bool() Property
	Method Juggle:Void(timePassed:Int)
End



Class Juggler<IJuggleable>
	Field list := New List<IJuggleable>
	Field _active:Bool = True
	
	Method Active:Bool() Property Return _active End
	Method Active:Void(active:Bool) Property _active = active End
	
	Method Add:Void(pin:IJuggleable)
		list.AddLast(pin)
	End
	
	Method Remove:Void(pin:IJuggleable)
		list.Remove(pin)
	End
	
	Method Update:Void(timePassed:Int)
		If _active = False Then Return
		For Local pin:IJuggleable = EachIn list
			If pin.Active
				pin.Juggle(timePassed)
			Endif
		Next
	End
End



Class AbuTimer
	Global unit:Int = UNIT_MILLISECONDS		'not implemented yet
	Global scale:Float = 1.0			'not implemented yet
	
	'[read-only]
	Method Delta:Int() Property
		If _paused
			Return _pausedDelta
		Else
			Return Time.Current() - _timeTarget
		Endif
	End
	
	'[read & write]
	Method Paused:Bool() Property Return _paused End
	Method Paused:Void(pausedNew:Bool) Property				'not strictly necessary
		If pausedNew
			Pause()
		Else
			Resume()
		Endif
	End
	
	Method New(timeTargetRelative:Int = 0)
		Set(timeTargetRelative)
	End
	
	Method Set:Void(timeTargetRelative:Int)		'timeTargetRelative is relative time in milliseconds
		Self._timeTargetRelative = timeTargetRelative
		Self._timeTarget = Time.Current() + _timeTargetRelative
	End
	
	Method Reset:Void()
		Self._timeTarget = Time.Current() + Self._timeTargetRelative
	End
	
	Method Pause:Void()
		If _paused Then Return
		_pausedDelta = Time.Current() - _timeTarget
		_paused = True
	End
	
	Method Resume:Void()
		If Not _paused Then Return 
		Set(-_pausedDelta)
		_paused = False
	End
	
	Method OnEnd:Void()
		'TODO
		'intended for extension
	End
	
Private		
	Field _timeTargetRelative:Int
	Field _timeTarget:Int
	
	Field _paused:Bool
	Field _pausedDelta:Int
End



Private

Class Time				'expose this?
	Global timeCurrent:Int
	Global timePrevious:Int
	Global timePassed:Int
	
	Function Update:Void()
		timePrevious = timeCurrent
		timeCurrent = Millisecs()			'TODO how to determine whether Millisecs() or RealMillisecs() should be used
		timePassed = timeCurrent - timePrevious
	End
	
	Function Current:Int()
		Return timeCurrent
	End
	
	Function Previous:Int()
		Return timePrevious
	End
	
	Function Tick:Int()
		Return timePassed
	End
End



Public

Function CurrentTime:Int()			'move this into Time?
	Return Time.Current()
End



Function Tick:Int()					'move this into Time?
	Return Time.Tick()
End



Function UpdateTime:Void()
	Time.Update()
End